package pers.bc.utils.aspect;

import java.time.Instant;
import java.time.temporal.ChronoUnit;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import pers.bc.utils.net.UserAgentUtil;
import pers.bc.utils.pub.DateUtilbc;
import pers.bc.utils.pub.LoggerUtil;
import pers.bc.utils.pub.PubEnvUtil;
import pers.bc.utils.pub.StringUtil;

/**
 * *
 *
 * @version 1.0<br>
 * @qualiFild MyDoneTimeAspect.java<br>
 * @author：LiBencheng<br>
 * @date Created on 2021年7月29日<br>
 */
@Aspect
@Component
public class AppMonitorRun
{
    public static Logger log = (Logger) LoggerFactory.getLogger(AppMonitorRun.class);
    LoggerUtil logUtil = LoggerUtil.getInstance("aspectLogs");
    
    @Around("@annotation(monitor)")
    public Object around(ProceedingJoinPoint joinPoint, AppMonitorRuning monitor) throws Throwable
    {
        // 当前的时间
        Instant starTime = Instant.now();
        // 这里获取到所有的参数值的数组
        Object[] args = joinPoint.getArgs();
        infoLog("开始调用{[%s]}的方法{[%s]},\r\n参数是：{[%s]}", monitor.funEffect(), monitor.method(), StringUtil.toString(args));
        Object obj = null;
        try
        {
            obj = joinPoint.proceed();
        }
        catch (Throwable e)
        {
            infoLog(getClientInfo(args));
            log.error("{[%s]}的方法{[%s]}->程序异常或出错：%s", monitor.funEffect(), monitor.method(), StringUtil.toString(e));
            infoLog("{[%s]}的方法{[%s]}->程序异常或出错：%s", monitor.funEffect(), monitor.method(), StringUtil.toString(e));
            logUtil.exception(e);
            throw new RuntimeException(e);
        }
        finally
        {
            infoLog("{[%s]}的方法{[%s]}束时间是：{[%s]}一共运行：{[%s ms]}，返回参数【%s】", monitor.funEffect(), monitor.method(),
                DateUtilbc.currentDateTime(), ChronoUnit.MILLIS.between(starTime, Instant.now()), StringUtil.toString(obj));
            logUtil.info(LoggerUtil.getSplitLine());
            
        }
        
        return obj;
    }
    
    private String getClientInfo(Object[] args)
    {
        for (int i = 0; i < PubEnvUtil.getSize(args); i++)
        {
            if (args[i] instanceof javax.servlet.http.HttpServletRequest)
                return UserAgentUtil.getCltInfo((javax.servlet.http.HttpServletRequest) args[i]);
            if (args[i] instanceof jakarta.servlet.http.HttpServletRequest)
                return UserAgentUtil.getCltInfo((jakarta.servlet.http.HttpServletRequest) args[i]);
        }
        return "没有获取到客户端信息!";
    }
    
    private void infoLog(String msg, Object... objs)
    {
        System.out.println(DateUtilbc.currentDateTime() + "：System.out.println方法调用日志---> " + String.format(msg, objs));
        log.info("方法调用日志 --->" + String.format(msg, objs));
        logUtil.info("方法调用日志 --->" + String.format(msg, objs));
    }
}
